package com.dhnsoft.tank;

import com.dhnsoft.game.Bullet;
import com.dhnsoft.game.Explode;
import com.dhnsoft.game.GameFrame;
import com.dhnsoft.map.MapBuff;
import com.dhnsoft.map.MapTile;
import com.dhnsoft.util.*;

import java.awt.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @Description
 * @ClassName Tank
 * @Author dhn
 * @date 2020.11.02 07:56
 * 坦克类
 */

public abstract class Tank {

    //坦克id号
    public int id;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    //四个方向
    public static final int DIR_UP=0;
    public static final int DIR_DOWN=1;
    public static final int DIR_LEFT=2;
    public static final int DIR_RIGHT=3;
    private int x,y;
    private String name;
    //半径
    public static final int RADIUS = 20;
    //默认速度
    public static final int DEFAULT_SPEED=8;
    //坦克的状态
    public static final int STATE_STAND=0;
    public static final int STATE_MOVE=1;
    public static final int STATE_DIE=2;
    //坦克的初始生命
    public static final int DEFAULT_HP=99;
    private int maxHP = DEFAULT_HP;
    private int hp=DEFAULT_HP;//血量
    private int atk;//攻击力
    public static final int ATK_MAX = 50;
    public static final int ATK_MIN = 50;


    public int speed;
    private int dir;
    private int state=STATE_STAND;
    private Color color;
    //是否为敌方坦克
    private boolean isEnemy = false;

    private BloodBar bar=new BloodBar();





    //炮弹
    private List<Bullet> bullets=new ArrayList();
    //使用容器来保存当前坦克上的所有的爆炸的效果
    private List<Explode> explodes=new ArrayList<>();

    public Tank(int x, int y, int dir) {
        this.x = x;
        this.y = y;
        this.dir = dir;
        this.speed=DEFAULT_SPEED;
        color = MyUtil.getRandomColor();
        name = MyUtil.getRandomName();
        atk=MyUtil.getRandomNumber(ATK_MIN,ATK_MAX);
    }

    public Tank() {
        color = MyUtil.getRandomColor();
        this.speed=DEFAULT_SPEED;
        name = MyUtil.getRandomName();
        atk=MyUtil.getRandomNumber(ATK_MIN,ATK_MAX);
    }

    /**
     * 绘制坦克
     */
    public void draw(Graphics g){
        logic();
        //g.setColor(color);
        //绘制坦克的圆
        //g.fillOval(x-RADIUS,y-RADIUS,RADIUS<<1,RADIUS<<1);
        drawTank(g);

        drawBullets(g);
        drawName(g);
        bar.draw(g);
    }
    public void draw2(Graphics g){
        logic();
        //g.setColor(color);
        //绘制坦克的圆
        //g.fillOval(x-RADIUS,y-RADIUS,RADIUS<<1,RADIUS<<1);
        drawTank(g);

        drawBullets(g);
        drawName(g);
        bar.draw2(g);
    }
    public void drawName(Graphics g){
        g.setColor(color);
        g.setFont(Constant.SMALL_FONT);
        g.drawString(name,x-RADIUS,y-40);
        //g.drawString("id:"+id,x-RADIUS,y-50);

    }
    public abstract void drawTank(Graphics g);
    //坦克的逻辑处理
    private void logic(){
        switch (state){
            case STATE_STAND:
                break;
            case STATE_MOVE:
                move();
                break;
            case STATE_DIE:
                break;
        }
    }
    private int oldX=-1,oldY=-1;
    //坦克移动的功能
    private void move(){
        oldX=x;
        oldY=y;
        switch (dir){
            case DIR_UP:
                y-=speed;
                if(y<RADIUS+25){
                    y=RADIUS+25;
                }
                break;
            case DIR_DOWN:
                y+=speed;
                if(y> Constant.FRAME_HEIGHT-RADIUS-23){
                    y=Constant.FRAME_HEIGHT-RADIUS-23;
                }
                break;
            case DIR_LEFT:
                x-=speed;
                if(x<RADIUS+5){
                    x=RADIUS+5;
                    x=RADIUS+5;
                }
                break;
            case DIR_RIGHT:
                x+=speed;
                if(x> Constant.FRAME_WIDTH-RADIUS-20){
                    x=Constant.FRAME_WIDTH-RADIUS-20;
                }
                break;
        }
    }

    public static int getDirUp() {
        return DIR_UP;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    public int getHp() {
        return hp;
    }

    public void setHp(int hp) {
        this.hp = hp;
    }

    public int getAtk() {
        return atk;
    }

    public void setAtk(int atk) {
        this.atk = atk;
    }

    public int getSpeed() {
        return speed;
    }

    public void setSpeed(int speed) {
        this.speed = speed;
    }

    public int getDir() {
        return dir;
    }

    public void setDir(int dir) {
        this.dir = dir;
    }

    public int getState() {
        return state;
    }

    public void setState(int state) {
        this.state = state;
    }

    public Color getColor() {
        return color;
    }

    public void setColor(Color color) {
        this.color = color;
    }

    public boolean isEnemy() {
        return isEnemy;
    }

    public void setEnemy(boolean enemy) {
        isEnemy = enemy;
    }

    public List<Bullet> getBullets() {
        return bullets;
    }

    public void setBullets(List<Bullet> bullets) {
        this.bullets = bullets;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getMaxHP() {
        return maxHP;
    }

    public void setMaxHP(int maxHP) {
        this.maxHP = maxHP;
    }

    @Override
    public String toString() {
        return "Tank{" +
                "speed=" + speed +
                '}';
    }

    //上一次开火时间
    private long fireTime;
    //子弹发射最小的间隔
    public static final int FIRE_INTERVAL = 300;
    /**
     * 坦克的功能，坦克开火的方法
     * 创建了一个子弹对象，子弹对象的属性信息通过坦克的信息获得
     * */
    public void fire(){
        //控制坦克开火时间
        if(System.currentTimeMillis()-fireTime>FIRE_INTERVAL){
            new Thread(()->new Audio("audio/tank_fire.wav").play()).start();
            int bulletX=x;
            int bulletY=y;
            switch (dir){
                case DIR_UP:
                    bulletY-=2*RADIUS;
                    break;
                case DIR_DOWN:
                    bulletY+=2*RADIUS;
                    break;
                case DIR_LEFT:
                    bulletX-=2*RADIUS;
                    break;
                case DIR_RIGHT:
                    bulletX+=2*RADIUS;
                    break;
            }

            //从子弹池中取数据
            Bullet bullet = BulletsPool.get();
            bullet.setX(bulletX);
            bullet.setY(bulletY);
            bullet.setDir(dir);
            bullet.setAtk(atk);
            bullet.setVisible(true);
            //Bullet bullet = new Bullet(bulletX, bulletY, dir, atk);
            bullets.add(bullet);

            //发射子弹之后，记录本次发射时间
            fireTime=System.currentTimeMillis();
        }

    }

    public void fire3() {
        //控制坦克开火时间
        if (System.currentTimeMillis() - fireTime > FIRE_INTERVAL) {
            new Thread(() -> new Audio("audio/tank_fire.wav").play()).start();
            int bulletX = x;
            int bulletY = y;
            for (int i = 0; i < 2
                    ; i++) {
                bulletY -= 2 * RADIUS;
                bulletY += 2 * RADIUS;
                bulletX -= 2 * RADIUS;
                bulletX += 2 * RADIUS;
                Bullet bullet = BulletsPool.get();
                bullet.setX(bulletX);
                bullet.setY(bulletY);
                bullet.setDir(i);
                bullet.setAtk(atk);
                bullet.setVisible(true);
                //Bullet bullet = new Bullet(bulletX, bulletY, dir, atk);
                bullets.add(bullet);
            }

            //从子弹池中取数据

            //发射子弹之后，记录本次发射时间
            fireTime = System.currentTimeMillis();
        }
    }
    public void fire2() {
        //控制坦克开火时间
        if (System.currentTimeMillis() - fireTime > FIRE_INTERVAL) {
            new Thread(() -> new Audio("audio/tank_fire.wav").play()).start();
            int bulletX = x;
            int bulletY = y;
            for (int i = 0; i < 4; i++) {
                bulletY -= 2 * RADIUS;
                bulletY += 2 * RADIUS;
                bulletX -= 2 * RADIUS;
                bulletX += 2 * RADIUS;
                Bullet bullet = BulletsPool.get();
                bullet.setX(bulletX);
                bullet.setY(bulletY);
                bullet.setDir(i);
                bullet.setAtk(atk);
                bullet.setVisible(true);
                //Bullet bullet = new Bullet(bulletX, bulletY, dir, atk);
                bullets.add(bullet);
            }

            //从子弹池中取数据

            //发射子弹之后，记录本次发射时间
            fireTime = System.currentTimeMillis();
        }
    }

    /**
     * 将当前坦克的发射的所有子弹绘制出来
     * */
    private void drawBullets(Graphics g){
        for (Bullet bullet : bullets) {
            bullet.draw(g);
        }
        //遍历所有的子弹，将不可见的子弹移除，并还原回对象池
        for (int i = 0; i < bullets.size(); i++) {
            Bullet bullet = bullets.get(i);
            if(!bullet.isVisible()){
                Bullet remove = bullets.remove(i);
                BulletsPool.theReturn(remove);
            }
        }
    }
    /*
    * 坦克销毁的时候处理坦克的所有子弹
    * */
    public void bulletsReturn(){
        for (Bullet bullet : bullets) {
            BulletsPool.theReturn(bullet);
        }
        bullets.clear();
    }

    //坦克和敌人的子弹碰撞的方法
    public void collideBullets(List<Bullet> bullets){
        //遍历所有的子弹，依次和当前的坦克进行碰撞的检测
        for (Bullet bullet : bullets) {
            int bulletX=bullet.getX();
            int bulletY=bullet.getY();

            //子弹和坦克碰上了
            if(MyUtil.isCollide(x,y,RADIUS,bulletX,bulletY)){
                //子弹消失
                bullet.setVisible(false);
                //坦克受到伤害
                hurt(bullet);
                //添加爆炸效果
                Explode explode = ExplodesPool.get();
                explode.setX(x);
                explode.setY(y-RADIUS);
                explode.setVisible(true);
                explode.setIndex(0);
                explodes.add(explode);
                new Thread(()->new Audio("audio/explode.wav").play()).start();
            }
        }
    }

    /*
    * 坦克受到伤害
    * */
    private void hurt(Bullet bullet){
        int atk = bullet.getAtk();
        System.out.println("atk = "+atk);
        hp-=atk;
        if(hp<0){
            hp=0;
            die();
        }
    }
    //坦克死亡需要处理的内容
    public void die(){
        if(isEnemy){
            GameFrame.killEnemyCount++;
            // 敌人坦克被消灭 归还对象池
            EnemyTanksPool.theReturn(this);
            //本关是否结束 TODO
            if(GameFrame.isCrossLevel()){
                //判断游戏是否通关
                if(GameFrame.isLastLevel()){
                    //通关
                    GameFrame.setGameState(Constant.STATE_WIN);
                }else {
                    //TODO 进入下一关
                    GameFrame.startCrossLevel();
                    new Thread(()->new Audio("audio/start.wav").play()).start();
                    //GameFrame.nextLevel();
                }


            }


        }else {
            //gameover
            delaySecondsToOver(1000);


        }
    }
    /*
    * 判断当前坦克是否死亡
    * */
    public boolean isDie(){
        return hp<=0
                ;
    }
    /*
    * 绘制所有的爆炸的效果
    * */
    public void drawExplodes(Graphics g){
        for (Explode explode : explodes) {
            explode.draw(g);
        }
        //将不可见的爆炸效果删除,还回对象池
        for (int i = 0; i < explodes.size(); i++) {
            Explode explode = explodes.get(i);
            if(!explode.isVisible()){
                Explode remove = explodes.remove(i);
                ExplodesPool.theReturn(remove);
            }
        }
    }
    /*
    * 坦克回退的方法
    * */
    public void back(){
        x=oldX;
        y=oldY;
    }

    /*
    * 血条的内部类
    * */
    class BloodBar{
        public static final int BAR_LENGTH = 50;
        public static final int BAR_HEIGHT=5;
        public void draw(Graphics g){
            //填充底色
            g.setColor(Color.YELLOW);
            g.fillRect(x-RADIUS,y-RADIUS-BAR_HEIGHT*2,BAR_LENGTH,BAR_HEIGHT);
            //红色的当前血量
            g.setColor(Color.RED);
            g.fillRect(x-RADIUS,y-RADIUS-BAR_HEIGHT*2,hp*BAR_LENGTH/maxHP,BAR_HEIGHT);
            //蓝色的边框
            g.setColor(Color.WHITE);
            g.drawRect(x-RADIUS,y-RADIUS-BAR_HEIGHT*2,BAR_LENGTH,BAR_HEIGHT);

        }
        public void draw2(Graphics g){
            //填充底色
            g.setColor(Color.YELLOW);
            g.fillRect(x-RADIUS,y-RADIUS-BAR_HEIGHT*2,BAR_LENGTH,BAR_HEIGHT);
            //红色的当前血量
            //g.setColor(Color.RED);
            //g.fillRect(x-RADIUS,y-RADIUS-BAR_HEIGHT*2,100*BAR_LENGTH/maxHP,BAR_HEIGHT);
            //蓝色的边框
            g.setColor(Color.WHITE);
            g.drawRect(x-RADIUS,y-RADIUS-BAR_HEIGHT*2,BAR_LENGTH,BAR_HEIGHT);

        }
    }
    //添加爆炸效果
    private void addExplode(int x,int y){
        //添加爆炸效果
        Explode explode = ExplodesPool.get();
        explode.setX(x);
        explode.setY(y-RADIUS);
        explode.setVisible(true);
        explode.setIndex(0);
        explodes.add(explode);
        new Thread(()->new Audio("audio/explode.wav").play()).start();

    }

    //坦克的子弹和地图块所有块的碰撞
    public void bulletsCollideMapTiles(List<MapTile> tiles){
        for (MapTile tile : tiles) {
            if(tile.isCollideBullet(bullets)){
                addExplode(tile.getX()+20,tile.getY());
                //水泥块没有击毁效果
                if(tile.getType()==MapTile.TYPE_HARD){
                    continue;
                }
                //设置地图块销毁
                tile.setVisible(false);
                //归还对象池
                MapTilePool.theReturn(tile);
                //当老巢被击毁之后，一秒钟切换到游戏结束页面
                if(tile.isHouse()){
                    delaySecondsToOver(1000);
                }
            }
        }
    }
    private void delaySecondsToOver(int millisSecond){
        new Thread(){
            @Override
            public void run() {
                try {
                    Thread.sleep(millisSecond);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                GameFrame.setGameState(Constant.STATE_OVER);
            }
        }.start();
    }

    public boolean isCollideBuff(MapBuff buff){
        if(!buff.isAtkVisible()){
            return false;
        }
        boolean collide = MyUtil.isCollide(x, y, RADIUS, buff.getX(), buff.getY());
        //如果碰上了就直接返回，否则继续判断下一个点
        if(collide){
            return true;
        }
        return false;
    }
    //速度buff
    public boolean isCollideSpeedBuff(MapBuff buff){
        if(!buff.isSpeedVisible()){
            return false;
        }
        boolean collide = MyUtil.isCollide(x, y, RADIUS, 720, 580);
        //如果碰上了就直接返回，否则继续判断下一个点
        if(collide){
            return true;
        }
        return false;
    }
    /*
    * 一个地图块和当前坦克碰撞的方法
    * 从tile中提取8个点，来判断8个点是否有任何一个点和当前坦克有了碰撞
    * 点的顺序从左上角的点开始，顺时针遍历
    * */
    public boolean isCollideTile(List<MapTile> tile){
        //正方形中心店和点的xy轴的距离
        for (MapTile mapTile : tile) {
            if(!mapTile.isVisible()||mapTile.getType()==MapTile.TYPE_COVER){
                continue;
            }
            int tileX = mapTile.getX();
            int tileY = mapTile.getY();
            boolean collide = MyUtil.isCollide(x, y, RADIUS, tileX, tileY);
            //如果碰上了就直接返回，否则继续判断下一个点
            if(collide){
                return true;
            }
            //点 -2 中上点
            tileX +=MapTile.radius;
            collide = MyUtil.isCollide(x, y, RADIUS, tileX, tileY);
            if(collide){
                return true;
            }
            //点 -3 右上角点
            tileX +=MapTile.radius;
            collide = MyUtil.isCollide(x, y, RADIUS, tileX, tileY);
            if(collide){
                return true;
            }
            //点 -4 右中点
            tileY +=MapTile.radius;
            collide = MyUtil.isCollide(x, y, RADIUS, tileX, tileY);
            if(collide){
                return true;
            }
            //点 -5 右下点
            tileY +=MapTile.radius;
            collide = MyUtil.isCollide(x, y, RADIUS, tileX, tileY);
            if(collide){
                return true;
            }
            //点 -6 下中点
            tileX -=MapTile.radius;
            collide = MyUtil.isCollide(x, y, RADIUS, tileX, tileY);
            if(collide){
                return true;
            }
            //点 -7 左下点
            tileX -=MapTile.radius;
            collide = MyUtil.isCollide(x, y, RADIUS, tileX, tileY);
            if(collide){
                return true;
            }
            //点 -8 左中点
            tileY -=MapTile.radius;
            collide = MyUtil.isCollide(x, y, RADIUS, tileX, tileY);
            if(collide){
                return true;
            }

        }
        return false;

    }
}
